refactor(types): retire the five forks that shadowed a @objectstack/spec vocabulary (#2944) - #2985
Merged
Merged
Conversation
…pec vocabulary (#2944) Five declarations in `@object-ui/types` restated a spec vocabulary, four of them re-exported under **the spec's own symbol name** — so an importer could not tell which definition they had. Every one had already drifted: ChartTypeSchema 7 → spec 19 ChartType 7 → spec 19 PageTypeSchema 4 → spec 5 (missing `list`) PageType 10 → spec 5 (five the spec explicitly repudiates) ReportType 3 → spec 4 (missing `joined`) ActionType 5 → spec 6 (missing `form`) All now come from the spec: the zod schemas by reference, the type aliases re-exported or derived via `z.infer`. This is why #2901 was filed with an inverted premise — it read the 7-value `ChartTypeSchema` as the protocol and concluded `plugin-charts` had outgrown it with renderer-local dialect. The spec has 19; the 7-value list was this fork. `ActionType`'s union carried a doc comment claiming to be "the canonical definition from @objectstack/spec" while missing `form`, which `ActionRunner.executeForm` implements — so a host app got a type error on code that works. Widening only: nothing was removed, so no existing value stops type-checking or validating. `PageType` keeps its five visualization names as `PageVisualizationAlias`, a named and documented local extension rather than names hidden inside a hand-written union. They are not page kinds (`ui/page.zod.ts` says so), but narrowing them away breaks anyone assigning `pageType: 'kanban'` — that is the separate cleanup the old comment referred to. Guards: `spec-subschema-parity.test.ts` pins both zod schemas by reference (a faithful copy fails — a copy is a fork); the new `spec-derived-unions.test.ts` covers the type aliases, which reference identity cannot reach, via `satisfies` plus runtime vocabulary assertions. Verified: 76/76 type-check tasks, 8215 tests across 700 files, eslint 0 errors. Closes #2944 Co-Authored-By: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
xuyushun441-sys
pushed a commit
that referenced
this pull request
Jul 30, 2026
Sync before merging so CI validates the real merge result — main picked up a @object-ui/types refactor (#2985) and two plugin-form wizard changes while this branch was in flight.
os-zhuang
added a commit
that referenced
this pull request
Jul 30, 2026
…aring one navigator (#2944) (#2994) The last open item of #2944. `ActionRunner` dispatched a seventh action type, `navigation`, that `@objectstack/spec`'s `ActionType` does not contain. The issue asked to promote it upstream or delete the case. Neither, as stated. Promoting is wrong: the spec already names this operation — `type: 'url'`, with `openIn` for the new-tab choice — so a seventh type would put a second spec name on one operation, which is the failure this audit exists to describe, committed one level up. Deleting is worse because it is silent: `{ type: 'navigation', to: … }` is authored today (`element:button` CTAs), and without the case the action falls through to `executeActionSchema`, which returns `{ success: true }` — a green toast that navigates nowhere (#2960's trap). The alias had already drifted, which is the actual finding. `executeNavigation` was quietly the weaker of two implementations of one concept: no `${param.X}` interpolation, `openIn` ignored, no `/api/…` full-page short-circuit. So `{ type: 'navigation', to: '/x?p=${param.p}' }` shipped the literal `${param.p}` while the identical `url` action resolved it. So it stays and stops being dialect. `ObjectUiLocalActionType` / `OBJECTUI_LOCAL_ACTION_TYPES` declare it as objectui's own alias of `url` — the treatment #2985 gave the page-visualization names — and both names now route through one `navigateTo`. `url` gains `replace` pass-through, the one modifier only the alias carried; `replace` is omitted from the `NavigationHandler` options when unset, so hosts see the shape they already saw. The guard is structural rather than another assertion: built-in dispatch is a table typed `Record<RunnableActionType, …>` instead of a `switch`, so an `ActionType` the spec ADDS stops compiling until an executor exists for it — #2942's "validates at save, renders nothing at run time" class, made a build error for actions. `spec-derived-unions.test.ts` additionally asserts `navigation` is absent from the spec enum, so the day it is adopted upstream the test fails and names the alias to retire. Also covers the `/api/` short-circuit and `apiBase` promotion, which had none — the project runs in a node env with no `window`, which is why — and corrects the audit doc's Direction B row, which still prescribed promoting. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This was referenced Jul 30, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2944.
Five declarations in
@object-ui/typesrestated a spec vocabulary, four of them re-exported under the spec's own symbol name — so an importer of@object-ui/typescould not tell which definition they had. Every one had already drifted.ChartTypeSchema(zod/data-display.zod.ts:209)ChartType(data-display.ts:689)PageTypeSchema(zod/layout.zod.ts:258)listPageType(layout.ts:432)ReportType(reports.ts:337)joinedActionType(ui-action.ts:72)formWhy this one mattered more than it looks
It is why #2901 was filed with an inverted premise. That issue read the 7-value
ChartTypeSchemaas the protocol and concludedplugin-chartshad outgrown it with 13 renderer-local names. The spec has 19 — the 7-value list was this fork, wearing the spec's name.ActionTypeis the same failure in miniature: its union carried a doc comment asserting it was "the canonical definition from @objectstack/spec" while missingform, whichActionRunner.executeFormimplements. A host app typing against@object-ui/typesgot a type error on code that works.The general shape, worth naming: the recurring failure is not "renderer forgot a name", it is "a second definition exists and the renderer is faithful to the wrong one."
Widening only
Nothing was removed, so no existing value stops type-checking or validating.
ActionTypegainsform,ReportTypegainsjoined,ChartTypegoes 7 → 19,PageTypeSchemagainslist.The
ChartTypewidening was the one real risk — an exhaustiveswitchwould stop being exhaustive. Checked: 76/76 type-check tasks pass, so there is none.PageTypeis not mechanical, and is handled differentlyNarrowing it to the spec's 5 would drop
grid/gallery/kanban/calendar/timeline— whichui/page.zod.tsexplicitly says are visualizations rather than page kinds, but which ap1-spec-alignmenttest asserts and which external code may assign.So the spec-owned half is now derived, and the objectui-only half is
PageVisualizationAlias— a named, documented, sanctioned local extension, which is what #2231 actually prescribes for genuine renderer-only concerns. The union is unchanged in membership; the difference is that the spec half can no longer drift and the local half is no longer hiding. Removing it is the separate "visualizations are not page types" cleanup.Guards
spec-subschema-parity.test.tsnow pins both zod schemas by reference —toBe, so a faithful copy fails too, because a copy is a fork.spec-derived-unions.test.tscovers the three type aliases, which reference identity cannot reach (types erase at runtime, and a restated union that happens to match is indistinguishable from a derived one). It usessatisfiesfor compile-time coverage plus runtime assertions that the spec enum still contains the specific members each fork had dropped.Verification
packages/typestsc🤖 Generated with Claude Code